package com.yds.developtools.utils

import android.content.Context
import android.content.SharedPreferences
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.util.*

/**
 * 作者:     YDS
 * 创建时间: 2023/5/29 13:34
 * 页面描述: SharePreferences-帮助类
 */
@Suppress("unused")
object YDSPreferencesHelper {
    private const val PreferenceName = "YDSP"

    /**
     * put string preferences
     *
     * @param key
     * @param value
     */
    fun Context.putString(key: String, value: String?): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putString(key, value)
        return editor.commit()
    }

    /**
     * get string preferences
     *
     * @param key
     */
    fun Context.getString(key: String): String? {
        return getString(key, null)
    }

    /**
     * get string preferences
     *
     * @param key
     * @param defaultValue
     */
    @Suppress("unused")
    fun Context.getString(key: String, defaultValue: String?): String? {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        return settings.getString(key, defaultValue)
    }

    /**
     * put int preferences
     *
     * @param key
     * @param value
     */
    fun Context.putInt(key: String, value: Int): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putInt(key, value)
        return editor.commit()
    }

    /**
     * get int preferences
     *
     * @param key
     */
    fun Context.getInt(key: String): Int {
        return getInt(key, -1)
    }

    /**
     * get int preferences
     *
     * @param key
     * @param defaultValue
     */
    @Suppress("unused")
    fun Context.getInt(key: String, defaultValue: Int): Int {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        return settings.getInt(key, defaultValue)
    }

    /**
     * put long preferences
     *
     * @param key
     * @param value
     */
    fun Context.putLong(key: String, value: Long): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putLong(key, value)
        return editor.commit()
    }

    /**
     * get long preferences
     *
     * @param key
     */
    fun Context.getLong(key: String): Long {
        return getLong(key, -1)
    }

    /**
     * get long preferences
     *
     * @param key
     * @param defaultValue
     */
    @Suppress("unused")
    fun Context.getLong(key: String, defaultValue: Long): Long {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        return settings.getLong(key, defaultValue)
    }

    /**
     * put float preferences
     *
     * @param key
     * @param value
     */
    fun Context.putFloat(key: String, value: Float): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putFloat(key, value)
        return editor.commit()
    }

    /**
     * get float preferences
     *
     * @param key
     */
    fun Context.getFloat(key: String): Float {
        return getFloat(key, -1f)
    }

    /**
     * get float preferences
     *
     * @param key
     * @param defaultValue
     */
    @Suppress("unused")
    fun Context.getFloat(key: String, defaultValue: Float): Float {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        return settings.getFloat(key, defaultValue)
    }

    /**
     * put boolean preferences
     *
     * @param key
     * @param value
     */
    fun Context.putBoolean(key: String, value: Boolean): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putBoolean(key, value)
        return editor.commit()
    }

    /**
     * get boolean preferences, default is false
     *
     * @param key
     */
    fun Context.getBoolean(key: String): Boolean {
        return getBoolean(key, false)
    }

    /**
     * get boolean preferences
     *
     * @param key
     * @param defaultValue
     */
    @Suppress("unused")
    fun Context.getBoolean(key: String, defaultValue: Boolean): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        return settings.getBoolean(key, defaultValue)
    }

    /**
     * 保存list
     *
     * @param tag
     * @param list
     * @return
     */
    fun Context.saveList(tag: String, list: List<String?>): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putInt(tag + "_size", list.size) /* sKey is an array */
        for (i in list.indices) {
            editor.remove(tag + "_" + i)
            editor.putString(tag + "_" + i, list[i])
        }
        return editor.commit()
    }

    /**
     * 取出list
     *
     * @param tag
     * @return List
     */
    fun Context.loadList(tag: String): List<String?> {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val size = settings.getInt(tag + "_size", 0)
        val list: MutableList<String?> = ArrayList()
        for (i in 0 until size) {
            list.add(settings.getString(tag + "_" + i, null))
        }
        return list
    }

    /**
     * 保存arraylist
     *
     * @param tag
     * @param arrayList
     * @return boolean
     */
    fun Context.saveArrayList(tag: String, arrayList: ArrayList<String?>): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putInt(tag + "_size", arrayList.size) /* sKey is an array */
        for (i in arrayList.indices) {
            editor.remove(tag + "_" + i)
            editor.putString(tag + "_" + i, arrayList[i])
        }
        return editor.commit()
    }

    /**
     * 取出arraylist
     *
     * @param tag
     * @return ArrayList
     */
    fun Context.loadArrayList(tag: String): ArrayList<String?> {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val size = settings.getInt(tag + "_size", 0)
        val arrayList = ArrayList<String?>()
        for (i in 0 until size) {
            arrayList.add(settings.getString(tag + "_" + i, null))
        }
        return arrayList
    }

    /**
     * 查询某个key是否已经存在
     *
     * @param key
     * @return boolean
     */
    operator fun Context.contains(key: String): Boolean {
        val sp: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        return sp.contains(key)
    }

    /**
     * 返回所有的键值对
     *
     * @return Map
     */
    fun Context.getAll(): Map<String?, *>? {
        val sp: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        return sp.all
    }

    /**
     * 移除某个key值已经对应的值
     *
     * @param key
     */
    fun Context.remove(key: String) {
        val sp: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = sp.edit()
        editor.remove(key)
        SharedPreferencesCompat.apply(editor)
    }

    /**
     * 清空SP
     *
     * @return boolean
     */
    fun Context.clearSharedPreference(): Boolean {
        val settings: SharedPreferences = getSharedPreferences(PreferenceName, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.clear()
        return editor.commit()
    }

    /**
     * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
     */
    private object SharedPreferencesCompat {
        private val sApplyMethod = findApplyMethod()

        /**
         * 反射查找apply的方法
         *
         * @return
         */
        private fun findApplyMethod(): Method? {
            try {
                val clz: Class<*> = SharedPreferences.Editor::class.java
                return clz.getMethod("apply")
            } catch (e: NoSuchMethodException) {
            }
            return null
        }

        /**
         * 如果找到则使用apply执行，否则使用commit
         *
         * @param editor
         */
        fun apply(editor: SharedPreferences.Editor) {
            try {
                if (sApplyMethod != null) {
                    sApplyMethod.invoke(editor)
                    return
                }
            } catch (e: IllegalArgumentException) {
            } catch (e: IllegalAccessException) {
            } catch (e: InvocationTargetException) {
            }
            editor.commit()
        }
    }
}